home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 051-075 / disk_069 / dk / dk.mod < prev   
Text File  |  1992-05-06  |  12KB  |  415 lines

  1.  
  2. (*$Q*)                        
  3.       
  4. MODULE DK;
  5.  
  6. (* A little fun, inspired by Leo Schwab's TILT *)
  7.  
  8. (* Author: Thomas H. Handel, PeopleLink ID -- THH -- *)
  9.  
  10. (* I'm still learning Modula-2 and programming on Amy, so this may not
  11.    be the tidiest or best way to do what the program does.  Also, it is
  12.    probably not the most elegant example of structured programming ever
  13.    created.  Finally, I am certain that there are many enhancements that 
  14.    more experienced programmers will be able to add (like maybe a close 
  15.    gadget and the wherewithall to respond to it).  Please fiddle at will.
  16.    If you have comments or suggestions, please contact me on PeopleLink or
  17.    by U.S. Snail at:
  18.  
  19.    628 Harberts Ct.
  20.    Annapolis, MD 21401
  21.  
  22.    Thanks in advance. *)
  23.  
  24. (* Placed in the Public Domain, 29 March 1987 *)
  25.  
  26. FROM SYSTEM IMPORT ADR, BYTE, NULL;
  27. FROM Intuition IMPORT NewWindow, WindowPtr, IntuitionName, IntuitionBase,
  28.                       WindowFlags, WindowFlagSet, IDCMPFlagSet,
  29.                       CloseWindowFlag, ScreenFlagSet, WBenchScreen,
  30.                       SmartRefresh,IntuiMessagePtr;
  31. FROM Libraries IMPORT OpenLibrary, CloseLibrary;
  32. FROM Windows IMPORT OpenWindow, CloseWindow;
  33. FROM Strings IMPORT String;
  34. FROM Pens IMPORT ReadPixel, WritePixel, SetAPen;
  35. FROM GraphicsLibrary IMPORT GraphicsName, GraphicsBase;
  36. FROM Ports IMPORT GetMsg, ReplyMsg, MessagePtr;
  37. FROM Rasters IMPORT RastPortPtr;
  38. FROM Storage IMPORT ALLOCATE, DEALLOCATE;
  39. FROM RandomNumbers IMPORT Random;
  40.  
  41. VAR WPtr: WindowPtr;
  42.     NWin: NewWindow;
  43.     WNam: String;
  44.     RprtPtr: RastPortPtr;
  45.     MsgPtr : IntuiMessagePtr;
  46.  
  47.  
  48.  
  49. PROCEDURE Initialize(): BOOLEAN;  (* Open the libraries *)
  50.  
  51. BEGIN
  52.    IntuitionBase := OpenLibrary(IntuitionName,0);
  53.    GraphicsBase := OpenLibrary(GraphicsName,0);
  54.    IF ((IntuitionBase = 0) OR (GraphicsBase = 0)) THEN RETURN FALSE
  55.       ELSE RETURN TRUE;
  56.    END;
  57. END Initialize;
  58.  
  59.  
  60. PROCEDURE InitWindow;  (* Set up and open the window *)
  61.  
  62. BEGIN
  63.    WNam := "DK!";
  64.    WITH NWin DO
  65.       LeftEdge := 450;
  66.       TopEdge := 0;
  67.       Width := 100;
  68.       Height := 10;
  69.       DetailPen := BYTE(0);
  70.       BlockPen := BYTE(1);
  71.       IDCMPFlags := IDCMPFlagSet{CloseWindowFlag};
  72.       Flags := SmartRefresh + WindowFlagSet{Activate, WindowClose,
  73.                WindowDepth};
  74.       FirstGadget := NULL;
  75.       CheckMark := NULL;
  76.       Title := ADR(WNam);
  77.       Screen := NULL;
  78.       BitMap := NULL;
  79.       MinWidth := 0;
  80.       MinHeight := 0;
  81.       MaxWidth := 0;
  82.       MaxHeight := 0;
  83.       Type := ScreenFlagSet{WBenchScreen};
  84.    END;
  85.    WPtr := OpenWindow(NWin);
  86. END InitWindow;
  87.  
  88.  
  89. PROCEDURE Decay; (* Erode the display *)
  90.  
  91.    TYPE ColNodePtr = POINTER TO ColNode;
  92.         ColNode = RECORD
  93.                     Col  : CARDINAL;  (* X-value of column *)
  94.                     Row  : CARDINAL;  (* Y-value of next non-zero pixel *)
  95.                     PClr : CARDINAL;  (* Pixel Pen number *)
  96.                     Next : ColNodePtr;  (* Forward pointer *)
  97.                     Prev : ColNodePtr  (* Backward pointer *)
  98.                   END;
  99.         PixlNodePtr = POINTER TO PixlNode;
  100.         PixlNode = RECORD
  101.                      PClr : CARDINAL; (* Pixel color *)
  102.                      CurX : CARDINAL; (* Current location, X-value *)
  103.                      CurY : CARDINAL; (* Current location, Y-value *)
  104.                      Next : PixlNodePtr; (* Forward pointer *)
  105.                      Prev : PixlNodePtr (* Backward pointer *)
  106.                    END;
  107.  
  108.    VAR ScrnTop   : CARDINAL;  (* Screen top *)
  109.        TopEdge   : CARDINAL;  (* Screen top less title bar *)
  110.        Bottom    : CARDINAL;  (* Screen bottom less border *)
  111.        YStrt     : CARDINAL;  (* Four pixels above bottom *)
  112.        ColCount  : CARDINAL;  (* Number of ColNodes in list *)
  113.        ColHead   : ColNodePtr; (* Pointer to head of ColNode list *)
  114.        CPtr      : ColNodePtr; (* Utility pointer for list traversal *)
  115.        PixlCount : CARDINAL;  (* Number of PixlNodes in list *)
  116.        PixlHead  : PixlNodePtr; (* Pointer to head of PixlNode list *)
  117.        PPtr      : PixlNodePtr; (* Utility pointer for list traversal *)
  118.        Depth     : ARRAY [2..637] OF CARDINAL; (* Depth of snow by col *)
  119.  
  120.  
  121.    PROCEDURE ComputeParms;  (* Get some basic parameters *)
  122.  
  123.    BEGIN
  124.       ScrnTop := WPtr^.WScreen^.TopEdge;
  125.       TopEdge := ScrnTop + 10;
  126.       Bottom := CARDINAL(WPtr^.WScreen^.Height) + ScrnTop - 1;
  127.       YStrt := Bottom - 4;
  128.    END ComputeParms;
  129.  
  130.  
  131.    PROCEDURE InitVars;  (* Initialize Variables *)
  132.  
  133.    VAR I : INTEGER; (* Counter *)
  134.  
  135.    BEGIN
  136.       FOR I := 2 TO 637 DO
  137.          Depth[I] := 0
  138.       END;
  139.       RprtPtr := ADR(WPtr^.WScreen^.RPort);
  140.       ColCount := 0;
  141.       PixlCount := 0;
  142.       ColHead := NIL;
  143.       PixlHead := NIL
  144.    END InitVars;
  145.  
  146.  
  147.    PROCEDURE FindCols;  (* Create list of cols containing non-zero pixls *)
  148.    VAR X    : CARDINAL; (* Column Counter *)
  149.        Y    : CARDINAL; (* Row Counter *)
  150.        Pixl : CARDINAL; (* Pen number of pixel *)
  151.  
  152.    BEGIN
  153.       FOR X := 2 TO 637 DO
  154.          Y := YStrt;
  155.          LOOP
  156.             Pixl := ReadPixel(RprtPtr,X,Y);
  157.             IF Pixl <> 0 THEN
  158.                NEW (CPtr);            (* Create node for list *)
  159.                CPtr^.Col := X;
  160.                CPtr^.Row := Y;
  161.                CPtr^.PClr := Pixl;
  162.                IF ColHead = NIL THEN  (* and link it in at head of list *)
  163.                   CPtr^.Next := NIL;
  164.                   CPtr^.Prev := NIL
  165.                ELSE
  166.                   CPtr^.Next := ColHead;
  167.                   CPtr^.Prev := NIL;
  168.                   ColHead^.Prev := CPtr
  169.                END;
  170.                ColHead := CPtr;
  171.                CPtr := NIL;
  172.                INC(ColCount);
  173.                EXIT
  174.             END;
  175.             Y := Y - 1;
  176.             IF Y <= TopEdge THEN
  177.                EXIT
  178.             END
  179.          END
  180.       END;
  181.    END FindCols;
  182.  
  183.  
  184.    PROCEDURE NewPixel;  (* Get a new pixel at random for snowflake ops *)
  185.  
  186.    VAR RNum : CARDINAL;  (* Random Number *)
  187.        I    : CARDINAL;  (* Counter *)
  188.        Pixl : CARDINAL;  (* Pen number of pixel *)
  189.  
  190.  
  191.       PROCEDURE DeleteCol;  (* Remove an empty column from the list *)
  192.  
  193.       BEGIN
  194.          IF CPtr = ColHead THEN
  195.             IF CPtr^.Next <> NIL THEN
  196.                ColHead := ColHead^.Next;
  197.                ColHead^.Prev := NIL
  198.             ELSE
  199.                ColHead := NIL
  200.             END
  201.          ELSE
  202.             IF CPtr^.Next = NIL THEN
  203.                CPtr^.Prev^.Next := NIL
  204.             ELSE
  205.                CPtr^.Prev^.Next := CPtr^.Next;
  206.                CPtr^.Next^.Prev := CPtr^.Prev
  207.             END
  208.          END;
  209.          DISPOSE (CPtr);
  210.          ColCount := ColCount - 1;
  211.       END DeleteCol;
  212.  
  213.  
  214.    BEGIN  (* NewPixel *)
  215.       RNum := Random(ColCount - 1);     (* 0 <= RNum <= [ColCount-1] *)
  216.       CPtr := ColHead;
  217.       IF RNum > 0 THEN
  218.          FOR I := 0 TO RNum DO
  219.             CPtr := CPtr^.Next
  220.          END
  221.       END;
  222.       NEW (PPtr);
  223.       PPtr^.PClr := CPtr^.PClr;
  224.       PPtr^.CurX := CPtr^.Col;
  225.       PPtr^.CurY := CPtr^.Row;
  226.       IF PixlHead = NIL THEN
  227.          PPtr^.Next := NIL;
  228.          PPtr^.Prev := NIL
  229.       ELSE
  230.          PPtr^.Next := PixlHead;
  231.          PPtr^.Prev := NIL;
  232.          PixlHead^.Prev := PPtr
  233.       END;
  234.       PixlHead := PPtr;
  235.       INC(PixlCount);
  236.       LOOP
  237.          CPtr^.Row := CPtr^.Row - 1;
  238.          IF CPtr^.Row < TopEdge THEN
  239.             DeleteCol;
  240.             EXIT
  241.          ELSE
  242.             Pixl := ReadPixel(RprtPtr,CPtr^.Col,CPtr^.Row);
  243.             IF Pixl <> 0 THEN
  244.                CPtr^.PClr := Pixl;
  245.                EXIT 
  246.             END
  247.          END
  248.       END;
  249.    END NewPixel;
  250.  
  251.  
  252.    PROCEDURE MovePixels;  (* Make the snow fall *)
  253.  
  254.    VAR XDest : CARDINAL;  (* Pixel destination, X-value *)
  255.        YDest : CARDINAL;  (* Pixel destination, Y-value *)
  256.        DFlag : BOOLEAN;  (* Signals pixel ready for deletion from list *)
  257.        RLFlag: BOOLEAN;  (* Direction of snow drift *)
  258.  
  259.  
  260.       PROCEDURE DeletePixel;  (* Remove a pixel from the list *)
  261.  
  262.       VAR tPtr : PixlNodePtr;  (* Utility pointer *)
  263.  
  264.       BEGIN
  265.          tPtr := PPtr;
  266.          IF PPtr = PixlHead THEN
  267.             IF PPtr^.Next <> NIL THEN
  268.                PixlHead := PixlHead^.Next;
  269.                PixlHead^.Prev := NIL
  270.             ELSE
  271.                PixlHead := NIL
  272.             END;
  273.             tPtr := PPtr;
  274.             PPtr := PixlHead
  275.          ELSE
  276.             IF PPtr^.Next = NIL THEN
  277.                PPtr^.Prev^.Next := NIL
  278.             ELSE
  279.                PPtr^.Prev^.Next := PPtr^.Next;
  280.                PPtr^.Next^.Prev := PPtr^.Prev
  281.             END;
  282.             tPtr := PPtr;
  283.             PPtr := PPtr^.Prev
  284.          END;
  285.          DISPOSE (tPtr);
  286.          PixlCount := PixlCount - 1;
  287.          DFlag := FALSE;
  288.       END DeletePixel;
  289.  
  290.  
  291.       PROCEDURE ComputeDest;  (* Compute a random destination for pixel *)
  292.  
  293.       BEGIN
  294.          XDest := PPtr^.CurX + 8 - Random(16);
  295.          YDest := PPtr^.CurY + Random(13);
  296.          IF XDest <= 2 THEN
  297.             XDest := 3 + Random(5)
  298.          END;
  299.          IF XDest >= 637 THEN
  300.             XDest := 636 - Random(5)
  301.          END;
  302.          IF YDest > Bottom - Depth[XDest] THEN
  303.             YDest := Bottom - Depth[XDest];
  304.             DFlag := TRUE
  305.          END;
  306.       END ComputeDest;
  307.  
  308.  
  309.       PROCEDURE Drift;  (* Keep the snow from stacking up in tall towers *)
  310.       VAR ChgFlag : BOOLEAN;  (* Flags change in XDest *)
  311.  
  312.  
  313.          PROCEDURE CheckLeft;  (* See if flake should drift left *)
  314.  
  315.          BEGIN
  316.             IF Depth[XDest] > Depth[XDest-1] THEN
  317.                XDest := XDest - 1;
  318.                ChgFlag := TRUE
  319.             END
  320.          END CheckLeft;
  321.  
  322.  
  323.          PROCEDURE CheckRight;  (* See if flake should drift right *)
  324.  
  325.          BEGIN
  326.             IF Depth[XDest] > Depth[XDest+1] THEN
  327.                INC(XDest);
  328.                ChgFlag := TRUE
  329.             END
  330.          END CheckRight;
  331.  
  332.       BEGIN (* Drift *)
  333.          ChgFlag := TRUE;
  334.          WHILE (XDest > 2) AND (XDest < 637) AND (ChgFlag) DO
  335.             ChgFlag := FALSE;
  336.             IF RLFlag THEN
  337.                CheckLeft;
  338.                CheckRight
  339.             ELSE
  340.                CheckRight;
  341.                CheckLeft
  342.             END;
  343.             YDest := Bottom - Depth[XDest] - 1
  344.          END
  345.       END Drift;
  346.  
  347.  
  348.       PROCEDURE MoveOne;  (* Move one pixel to new destination *)
  349.  
  350.       BEGIN
  351.          SetAPen(RprtPtr,0);
  352.          WritePixel(RprtPtr,PPtr^.CurX,PPtr^.CurY);
  353.          SetAPen(RprtPtr,PPtr^.PClr);
  354.          WritePixel(RprtPtr,XDest,YDest);
  355.          PPtr^.CurX := XDest;
  356.          PPtr^.CurY := YDest;
  357.       END MoveOne;
  358.  
  359.    BEGIN (* MovePixels *)
  360.       RLFlag := TRUE;
  361.       DFlag := FALSE;
  362.       PPtr := PixlHead;
  363.       WHILE PPtr <> NIL DO           (* While there are still flakes *)
  364.          ComputeDest;                (* Find this one a new destination *)
  365.          IF DFlag THEN               (* If it has landed *)
  366.             Drift;                   (* See if it should roll R or L *)
  367.             RLFlag := NOT(RLFlag)
  368.          END;
  369.          MoveOne;                    (* Actually move it to new dest *)
  370.          IF DFlag THEN               (* If it has landed *)
  371.             INC(Depth[XDest]);       (* increment depth in column *)
  372.             DeletePixel              (* and remove pixel from list *)
  373.          END;
  374.          IF PPtr <> NIL THEN
  375.             PPtr := PPtr^.Next
  376.          END
  377.       END
  378.    END MovePixels;
  379.    PROCEDURE DanceOff;  (* Clean things up *)
  380.  
  381.    BEGIN
  382.       CloseWindow(WPtr);
  383.       CloseLibrary(IntuitionBase);
  384.       CloseLibrary(GraphicsBase);
  385.    END DanceOff;
  386.  
  387. BEGIN (* Decay *)
  388.    ComputeParms;
  389.    InitVars;
  390.    FindCols;
  391.    REPEAT
  392.       IF ColCount <> 0 THEN  
  393.          NewPixel
  394.       END;
  395.       IF PixlCount <> 0 THEN
  396.          MovePixels
  397.       END;
  398.    MsgPtr := GetMsg(WPtr^.UserPort);
  399.    IF MsgPtr <> NULL THEN
  400.       ColCount := 0;
  401.       PixlCount := 0;
  402.       ReplyMsg (MessagePtr(MsgPtr));
  403.    END;
  404.    UNTIL (ColCount = 0) AND (PixlCount = 0);
  405.    DanceOff;
  406. END Decay;
  407.  
  408.  
  409. BEGIN (* DK *)
  410.    IF Initialize() THEN
  411.      InitWindow;
  412.      Decay;
  413.    END;
  414. END DK.
  415.